package com.sinodata.bsm.cicp.collector.common;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.Collector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.cicp.util.CommandReader;
import com.sinodata.bsm.common.vo.ResPropertyValue;

/**
 * 
 * <p>
 * Description: 
 *   通过正则表达式Regex匹配单个shell的采集。
 *   如果shell命令采集到多行，则返回多组值
 *   
 *   新增采集值映射功能，例如：map = "$1 正确采集值?正确映射值:不正确时的映射值;$2 正确采集值?正确映射值:不正确时的映射值;"
 *                         其中$n表示Regex参数中的第n组
 *   应用场景举例：cmd = "echo success";regex = "(\\w+)"; map = "$1 success?1:0";当命令正确返回success时指标值是1,否则是0；
 *
 * </p>
 *
 * @author wangpeng
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-8-10 上午10:09:16          wangpeng        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class RegexMatchShellCollector extends Collector {

    private static final Logger logger = Logger.getLogger(RegexMatchShellCollector.class);

    /**
     * 
     */
    public RegexMatchShellCollector() {

    }

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        String cmd = this.paramMap.get("collectCmd");
        String regex = this.paramMap.get("Regex");
        String map = this.paramMap.get("Map");
        Map<Integer, List<String>> mapMap = getMapGroup(map);
        Pattern pattern = Pattern.compile(regex);
        BufferedReader reader = null;
        List<ResPropertyValue> values = new ArrayList<ResPropertyValue>();
        String[] propMetas = getPropMeta();
        try {
            reader = CommandReader.getReader(ip, cmd, (int) this.interval, 0);
            String readLine = null;
            while ((readLine = reader.readLine()) != null) {
                readLine = readLine.trim();
                Matcher matcher = pattern.matcher(readLine);
                if (matcher.find()) {
                    ResPropertyValue propertyValueX = new ResPropertyValue();
                    ResPropertyValue.PropValue[] propValues = new ResPropertyValue.PropValue[matcher.groupCount()];
                    for (int i = 0; i < propValues.length; i++) {
                        String field = matcher.group(i + 1);
                        if (mapMap == null || mapMap.size() == 0) {
                            propValues[i] = ResPropertyValue.createPropValue(field, propMetas[i]);
                        } else {
                            List<String> list = mapMap.get(i + 1);
                            propValues[i] = ResPropertyValue.createPropValue(list.get(0).equals(field) ? list.get(1) : list.get(2), propMetas[i]);
                        }
                    }
                    propertyValueX.setValues(propValues);
                    values.add(propertyValueX);
                }
            }
        } catch (Exception e) {
            logger.error("failed to collect by RegexMatchShellCollector", e);
            throw new CollectorException(e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {

                }
            }
        }
        return values;
    }

    @Override
    public String[] getParamMeta() {
        return new String[] { "collectCmd", "Regex" };
    }

    @Override
    public String[] getPropMeta() {
        String regex = this.paramMap.get("Regex");
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher("");
        int count = matcher.groupCount();
        String[] propMetas = new String[count];
        for (int i = 1; i <= propMetas.length; i++) {
            propMetas[i - 1] = "$" + i;
        }
        return propMetas;
    }

    private Map<Integer, List<String>> getMapGroup(String map) {
        if (map == null || map.trim().equals("")) {
            return null;
        }
        map = map.trim();
        String regex = "(\\$\\d+\\s+\\S+\\?\\S+:\\S+;)+";
        String regexGrop = "\\$(\\d+)\\s+(\\S+)\\?(\\S+):(\\S+)";
        Pattern pattern = Pattern.compile(regexGrop);
        if (!map.matches(regex)) {
            logger.error("Map 参数格式错误：$n 正确采集值?正确映射值:不正确时的映射值;。一定以分号结尾");
            return null;
        }
        Map<Integer, List<String>> mapGroup = new HashMap<Integer, List<String>>();
        String[] groups = map.split(";");
        for (String group : groups) {
            Matcher matcher = pattern.matcher(group);
            if (matcher.find()) {
                Integer key = Integer.parseInt(matcher.group(1));
                List<String> value = new ArrayList<String>();
                mapGroup.put(key, value);
                value.add(matcher.group(2));
                value.add(matcher.group(3));
                value.add(matcher.group(4));
            } else {
                return null;
            }
        }
        return mapGroup;
    }
}
